package identx

import (
	"gitee.com/zhongguo168a/gocodes/datax/stringx"
	"gitee.com/zhongguo168a/gocodes/myx/scale"
	"math/rand"
	"sync"
	"sync/atomic"
	"time"
)

func init() {
	originTime = 1199116800
	identString = NewIdentString()
	identString.updateTimeString()
	identString.resetObjectIDCounter()

	//SetNode(3844 + rander.Intn(238328-3844))
}

var identString *IdentString
var node string

const daySecond = 10000

func NewIdentString() (obj *IdentString) {
	obj = &IdentString{}
	obj.rander = rand.New(rand.NewSource(time.Now().UnixNano()))
	obj.scaleN = 62
	obj.countChange = daySecond
	obj.lastTimestamp = timeGen()
	return
}

type IdentString struct {
	rander          *rand.Rand
	objectIDCounter uint32
	mutex           sync.Mutex

	lastTimestamp int64

	// 固定长度6
	timeString string
	scaleN     int
	// 每N次更新一次 [objectIDCounter]
	countChange int
}

//func readRandomUint32() uint32 {
//	var b [4]byte
//	_, err := io.ReadFull(rand.Reader, b[:])
//	if err != nil {
//		panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
//	}
//
//	return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24)
//}
//
//func readRandomUint16() uint16 {
//	var b [2]byte
//	_, err := io.ReadFull(rand.Reader, b[:])
//	if err != nil {
//		panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
//	}
//
//	return (uint16(b[0]) << 0) | (uint16(b[1]) << 8)
//}
func (is *IdentString) resetObjectIDCounter() {
	//is.objectIDCounter = uint32(3844 + is.rander.Intn(65535-3844))
	is.objectIDCounter = uint32(0)
}

func SetNode(val string) {
	//node = scale.DecimalTo(val, scaleN)
	//node = stringx.FillFirst(node, 3, "0")
	node = val
}

//func ParseTime(ident string) int64 {
//	lastident := make([]byte, len(ident))
//	lastident[0] = ident[0]
//	for i := 1; i < len(lastident); i++ {
//		c := ident[i]
//		lastident[i] = normalChar(ident[0], c)
//	}
//	ts := string(lastident[:6])
//	ts = stringx.Reverse(ts)
//	return 0
//}

func (is *IdentString) updateTimeString() {
	is.timeString = scale.DecimalTo(int(is.lastTimestamp), is.scaleN)
	//is.timeString = stringx.FillFirst(is.timeString, 6, "0")
	is.timeString = stringx.Reverse(is.timeString)
}

var originTime int64

func timeGen() int64 {
	//return 1637829423
	//return slowtime.Now().Unix()
	return time.Now().Unix() - originTime
}

// prefix必须小于scaleN
func (is *IdentString) GenOneWithIntPrefix(prefix int) string {
	return scale.DecimalTo(prefix, is.scaleN) + GenOne()
}

// prefix只能是一个字符
func (is *IdentString) GenOneWithStringPrefix(prefix string) string {
	return prefix + GenOne()
}

func (is *IdentString) GenOne() string {
	is.mutex.Lock()
	defer is.mutex.Unlock()
	now := timeGen()
	if now > is.lastTimestamp {
		is.lastTimestamp = now
		is.resetObjectIDCounter()
		is.updateTimeString()
	}
	count := atomic.AddUint32(&is.objectIDCounter, 1)
	countString := scale.DecimalTo(int(count), is.scaleN)
	countLength := scale.DecimalTo(len(countString), is.scaleN)
	//countString = stringx.FillFirst(countString, 4, "0")
	ident := is.timeString + countLength + countString + node
	//lastident := make([]byte, len(ident))
	//ruleChar := ident[0]
	//lastident[0] = ruleChar
	//for i := 1; i < len(lastident); i++ {
	//	c := ident[i]
	//	lastident[i] = confuseChar(ruleChar, c)
	//}
	//if _, ok := congfu.Load(string(lastident)); ok {
	//	fmt.Println("chongfu2", ident, string(lastident))
	//}
	//congfu.Store(string(lastident), true)
	//ident = string(lastident)

	// 6+1+4 = 12位
	return ident
}

// GenOne [tag] 用于标识字符串的用途
func GenOne() string {
	return identString.GenOne()
}
